#include "HttpRequest.h"

NetWork::HttpRequest::HttpRequest() :
    ParseState(State::Line)
{
}

NetWork::HttpRequest::HttpRequest(Buffer &&requestData) :
    RequestData(std::move(requestData)), ParseState(State::Line)
{
    Parse();
}

void NetWork::HttpRequest::Parse(const void *requestData, size_t len)
{
    RequestData.RetrieveAll();
    RequestData.Wirte(requestData, len);

    Parse();
}

inline const std::unordered_map<std::string, std::string> &NetWork::HttpRequest::GetHeaders() const
{
    return Headers;
}

inline const NetWork::Buffer &NetWork::HttpRequest::GetBody() const
{
    return Body;
}

inline const std::string &NetWork::HttpRequest::GetMethod() const
{
    return Method;
}

inline const std::string &NetWork::HttpRequest::GetUrl() const
{
    return Url;
}

inline const std::string &NetWork::HttpRequest::GetProtocolVersion() const
{
    return ProtocolVersion;
}

void NetWork::HttpRequest::Parse()
{
    while (ParseState != State::Finish && 
        RequestData.GetReadable() != 0) {
        switch (ParseState)
        {
        case State::Line:
            ParseLine();
            ParseState = State::Headers;
            break;

        case State::Headers:
            ParseHeaders();
            ParseState = State::Body;
            break;

        case State::Body:
            ParseBody();
            ParseState = State::Finish;
            break;

        default:
            break;
        }
    }
}

void NetWork::HttpRequest::ParseLine()
{
    std::string requestData(RequestData.ReadableBegin(), RequestData.ReadableEnd());
    auto line = requestData.substr(0, requestData.find("\r\n"));
    
    //使用正则表达式进行分词
    std::regex reg(" ");
    std::sregex_token_iterator pos(line.begin(), line.end(), reg, -1);
    decltype(pos) end;

    std::vector<std::string> results;
    for (; pos != end; pos++)
        results.push_back(pos->str());

    if (results.size() == 3) {
        Method = std::move(results[0]);
        Url = std::move(results[1]);
        ProtocolVersion = std::move(results[2]);
    }

    RequestData.Retrieve(line.size() + 2);
}

void NetWork::HttpRequest::ParseHeaders()
{
    std::string requestData(RequestData.ReadableBegin(), RequestData.ReadableEnd());
    auto headers = requestData.substr(0, requestData.find_last_of("\r\n") - 1);

    std::regex reg("\r\n");
    std::sregex_token_iterator pos(headers.begin(), headers.end(), reg, -1);
    decltype(pos) end;

    //Headers per line
    for (; pos != end; pos++) {
        std::string kv(pos->str());
        std::regex reg_kv(" ?: ?");
        std::sregex_token_iterator pos_kv(kv.begin(), kv.end(), reg_kv, -1);
        
        Headers.insert({pos_kv->str(), (++pos_kv)->str()});
    }

    RequestData.Retrieve(headers.size() + 2);
}

void NetWork::HttpRequest::ParseBody()
{
    Body.Wirte(RequestData.ReadableBegin(), RequestData.GetReadable());
    RequestData.RetrieveAll();
}
